﻿#include "chatsocket.h"
#include "chatsetchange.h"
#include "registerui.h"
#include "widget.h"
#include "friendrequestlist.h"
#include "freindwidget.h"

ChatSocket* ChatSocket::m_pChatSocket;
ChatSocket::ChatSocket()
{
    m_pChatSocket = nullptr;
    m_bisInit = false;
    m_ConnectionStatus = false;
}

ChatSocket::~ChatSocket()
{
    unInit();
}

bool ChatSocket::intiAll()
{
    if(!m_bisInit)
    {
        QString ip = Conf::getInstance()->m_ip;
        uint chatPort = Conf::getInstance()->m_chatPort;
        uint imgPort = Conf::getInstance()->m_imgPort;
        uint filePort = Conf::getInstance()->m_filePort;
        uint videoPort = Conf::getInstance()->m_videoPort;
        uint audioPort = Conf::getInstance()->m_audioPort;
        m_pChatSock = new QTcpSocket;
        m_pImgSock = new QTcpSocket;
        m_pFileSock = new QTcpSocket;
        m_pVideoSock = new QTcpSocket;
        m_pAudioSock = new QTcpSocket;
        m_pChatSock->connectToHost(QHostAddress(ip),chatPort);
        m_pImgSock->connectToHost(QHostAddress(ip),imgPort);
        m_pFileSock->connectToHost(QHostAddress(ip),filePort);
        m_pVideoSock->connectToHost(QHostAddress(ip),videoPort);
        m_pAudioSock->connectToHost(QHostAddress(ip),audioPort);
        m_bisInit = true;
        connect(m_pChatSock,&QTcpSocket::readyRead,this,&ChatSocket::handleChatDate);
        connect(m_pChatSock,&QTcpSocket::stateChanged,this,&ChatSocket::handleStatuChange);
    }
    return m_bisInit;
}

void ChatSocket::unInit()
{
    if(m_bisInit)
    {
        m_pChatSock->disconnectFromHost();
        m_pImgSock->disconnectFromHost();
        m_pFileSock->disconnectFromHost();
        m_pVideoSock->disconnectFromHost();
        m_pAudioSock->disconnectFromHost();
        delete m_pChatSock;
        delete m_pImgSock;
        delete m_pFileSock;
        delete m_pVideoSock;
        delete m_pAudioSock;
        delete m_pChatSocket;
        m_pChatSocket = nullptr;
    }
}

ChatSocket *ChatSocket::getInstance()
{
    if(m_pChatSocket == nullptr)
        m_pChatSocket = new ChatSocket;
    return m_pChatSocket;
}

void ChatSocket::handleLoginS(Json::Value& root)
{
    createFileAndWriteAcount();
    QList<UserInfo> listU;
    //读取好友信息
    for(int i=0;i < root["Friends"].size();++i)
    {
        UserInfo u;
        u.id = root["Friends"][i]["ID"].asCString();
        u.nickname = root["Friends"][i]["NickName"].asCString();
        int fstatus = root["Friends"][i]["Status"].asInt();
        u.headurl = root["Friends"][i]["HeadUrl"].asCString();
        u.online = fstatus;
        listU.append(u);
    }
    //更新好友信息到自己的数据库
//    ChatDB::getInstance()->updateUserInfo(root["Friends"],1);
    //读取群聊信息
    QList<groupinfo> listG;
    for(int i = 0;i < root["Groups"].size(); ++i)
    {
        groupinfo g;
        std::string gname = root["Groups"][i]["GNickName"].asString();
        std::string gheadpath = root["Groups"][i]["GHeadPath"].asString();
        std::string gid = root["Groups"][i]["GID"].asString();
        strcpy(g.gid,gid.c_str());
        strcpy(g.gimg,gheadpath.c_str());
        strcpy(g.gname,gname.c_str());
        listG.append(g);
    }
    //发送请求离线聊天记录
    Json::Value value;
    value["TYPE"] = REQUEST_OFFLINELOG;
    value["UID"] = m_userID.toStdString();
    QString strJson(value.toStyledString().c_str());
    int len = strJson.toUtf8().length();
    m_pChatSock->write((char*)&len,sizeof len);
    m_pChatSock->write(strJson.toUtf8(),strJson.toUtf8().length());

    //创建用户数据库
    QString str = QCoreApplication::applicationDirPath();
    QString path = QString("%1/%2/ChatDB.db").arg(str).arg(m_userID);
    ChatDB::getInstance()->initUserDB(path);

    //显示主窗口
    if(root["self"].isArray())//更新个人信息到数据库
    {
        ChatDB::getInstance()->updateUserInfo(root["self"][0],0);
        QString Id = root["self"][0]["ID"].asCString();
        QString nickName = root["self"][0]["NickName"].asCString();
        QString headUrl = root["self"][0]["HeadUrl"].asCString();
        ChatDB::getInstance()->addUser(Id,nickName,headUrl);
    }
    MainWidget::getInstance()->init(m_userID);
    MainWidget::getInstance()->loadFriendAndLoadGroup(listU,listG);
    MainWidget::getInstance()->show();
    emit ChatSocket::transMSG(MsgType::LOGINS);
}

void ChatSocket::createFileAndWriteAcount()
{
    //创建用户文件夹
    QString str = QCoreApplication::applicationDirPath();
    QString path = QString("%1/%2").arg(str).arg(m_userID);
    QDir dir(path);
    if(!dir.exists())
    {
        dir.mkdir(path);
        QString filename = QString("%1/user.json").arg(path);
        QFile file(filename);
        if(!file.open(QIODevice::WriteOnly))
        {
            qDebug()<<"[ChatSocket::createFileAndWriteAcount()]=>create file fail\n";
            return;
        }
        Json::Value root;
        root["id"] = m_userID.toStdString();
        if(m_isSavePwd)
            root["pwd"] = m_pwd.toStdString();
        file.write(root.toStyledString().c_str());
        file.flush();
        file.close();
    }
}

void ChatSocket::OnRegister(QString nickname, QString pwd)
{
    Json::Value root;
    root["TYPE"] = RES;
    root["nickname"] = nickname.toStdString();
    root["pwd"] = pwd.toStdString();
    QString strJson(root.toStyledString().c_str());
    int len = strJson.toUtf8().length();
    m_pChatSock->write((char*)&len,sizeof len);
    m_pChatSock->write(strJson.toUtf8(),strJson.toUtf8().length());
}

void ChatSocket::sendChatData(Json::Value &root)
{
    QString strJson(root.toStyledString().c_str());
    int len = strJson.toUtf8().length();
    m_pChatSock->write((char*)&len,sizeof len);
    m_pChatSock->write(strJson.toUtf8(),strJson.toUtf8().length());
}

QString ChatSocket::getUserID()
{
    return m_userID;
}


void ChatSocket::handleRecvMsg(Json::Value& root)
{
    //播放提示音
//    m_MediaPlayer->setMedia(QUrl::fromLocalFile("D:\\QTCode5.14\\CClient\\res\\tip.mp3"));
//    m_MediaPlayer->setVolume(100);
//    m_MediaPlayer->play();
    QString sender(root["sender"].asCString());
    QString time(root["time"].asCString());
    QString msg(root["msg"].asCString());
    for(auto x:m_chatList)
    {
        QString nickname = ChatDB::getInstance()->getNickName(sender);
        QString text = nickname+"("+sender+")";
        if(text==x->getWinName())
        {
            QWidget* widget = x->CreateWidgetL_R(1,sender,msg);
            x->addMsgWidget(widget);
            //将消息追加到文件
            QString str = QCoreApplication::applicationDirPath();
            QString filename = QString("%1/%2/%3-%4.txt").arg(str).arg(m_userID).arg(m_userID).arg(sender);
            QFile file(filename);
            if(!file.open(QIODevice::ReadWrite|QIODevice::Append))
                QMessageBox::warning(NULL,"警告","创建文件失败");
            QString senderinfo = sender + "&" + time + "\r\n";//谁发的什么时候发的
            file.write(senderinfo.toStdString().c_str());
            msg = "わ" + msg + "わ\r\n";
            file.write(msg.toStdString().c_str());
            file.close();
//            userInfo u2;
//            memset(&u2,0,sizeof (u2));
//            strcpy(u2.name,u.pwd);
//            MainUI::getInstance().updateFriendList(u2,-1,msg);
            //让系统托盘显示消息
//            m_trayIcon.showMessage("有新消息",oname+":"+QString(msg),QSystemTrayIcon::Information);
            return;
        }
    }
//    ChatWidget* privateChat = new ChatWidget;
//    QString nickname = ChatDB::getInstance()->getNickName(u.pwd);
//    QString text = nickname+"("+QString(u.pwd)+")";
//    privateChat->setWinName(text);
//    createTextMsgConnection(privateChat);//为其创建发送消息的连接
//    privateChat->insertFrienNameToList(text);
//    privateChat->setSelectFriend(text);
    //将消息更新到列表
//    userInfo u2;
//    memset(&u2,0,sizeof (u2));
//    strcpy(u2.name,u.pwd);
//    MainUI::getInstance().updateFriendList(u2,-1,msg);

    //查找有无聊天记录
    QString str = QCoreApplication::applicationDirPath();
    QString filename = QString("%1/%2/%3-%4.txt").arg(str).arg(m_userID).arg(m_userID).arg(sender);
    //将消息追加到文件
    QFile file2(filename);
    if(!file2.open(QIODevice::ReadWrite|QIODevice::Append))
    {
        QMessageBox::warning(NULL,"警告","创建文件失败");
        return;
    }
    QString senderinfo = sender + "&" + time + "\r\n";//谁发的什么时候发的
    file2.write(senderinfo.toStdString().c_str());
    msg = "わ" + msg + "わ\r\n";
    file2.write(msg.toStdString().c_str());
    file2.close();
    //让系统托盘显示消息
//    m_trayIcon.showMessage("有新消息",oname+":"+QString(msg),QSystemTrayIcon::Information);
}

void ChatSocket::handleOffLineLog(Json::Value& root)
{
    QString msg;
    if(!root["content"].isNull())
        msg = root["content"].asCString();
    qDebug()<<msg<<endl;
    QStringList list = msg.split("\n");
    //处理离线聊天记录
    for(int i=0;i<list.size()-1;i+=2)
    {
        QStringList list2 = list[i].split("&");//取出账号id和发送时间
        QString nickname = ChatDB::getInstance()->getNickName(list2[0]);
        QString text = nickname+"("+list2[0]+")";
        QString info = list[i+1].replace("わ","");//取出消息内容
        //将消息追加到文件
        QString str = QCoreApplication::applicationDirPath();
        QString filename = QString("%1/%2/%3-%4.txt").arg(str).arg(m_userID).arg(m_userID).arg(list2[0]);
        QFile file(filename);
        if(!file.open(QIODevice::ReadWrite|QIODevice::Append))
        {
            QMessageBox::warning(NULL,"警告","创建文件失败");
            return;
        }
//        userInfo u;
//        strcpy(u.name,list2[0].toStdString().c_str());
//        MainUI::getInstance().updateFriendList(u,-1,info);
        QString current_date;
        current_date = QString(list2[0]) +"&" + list2[1];
        current_date+="\r\n";
        file.write(current_date.toStdString().c_str());
        QString Msg(info);
        Msg = "わ" + Msg + "わ\r\n";
        file.write(Msg.toStdString().c_str());
        file.close();
    }
    //处理离线好友请求
    if(root["Request"].isArray())
    {
        for(int i = 0; i < root["Request"].size(); i++)
        {
            root["Request"][i]["Status"] = -1;//-1 未处理 0 待处理  1 已处理
        }
        QString str = QCoreApplication::applicationDirPath();
        QString path = QString("%1/%2/friendRequest.json").arg(str).arg(m_userID);
        FILE* fp = NULL;
        fp = fopen(path.toStdString().c_str(),"r");
        if(fp == NULL)
        {
            fp = fopen(path.toStdString().c_str(),"w");
            if(fp)
            {
                std::string content = root["Request"].toStyledString();
                fwrite(content.c_str(),strlen(content.c_str()),1,fp);
                fflush(fp);
                fclose(fp);
                return;
            }
        }
        else
        {
            fseek(fp, 0, SEEK_END);
            int len = ftell(fp);
            fseek(fp, 0, SEEK_SET);
            char* buff = new char[len + 1];
            fread(buff, len, 1, fp);
            buff[len] = 0;
            Json::Reader reader;
            Json::Value temp;
            if (reader.parse(buff, temp))
            {
                fclose(fp);
                fp = NULL;
                fp = fopen(path.toStdString().c_str(), "w");
                if (fp)
                {
                    for (int i = 0; i < root["Request"].size(); ++i)
                    {
                       temp["Request"].append(root["Request"][i]);
                    }
                    std::string content = temp.toStyledString();
                    int len = strlen(content.c_str());
                    fwrite(content.c_str(), len, 1, fp);
                    fflush(fp);
                    fclose(fp);
                }
            }
            delete [] buff;
            buff = nullptr;
        }
    }
}

void ChatSocket::hanldeOnlineStatus(QString id, bool status)
{
    MainWidget::getInstance()->changeUserStatus(id,status);
}

void ChatSocket::handleAddFriend(Json::Value &root)
{
    FriendRequestList* fw = FriendRequestList::getInstance();
    UserInfo userinfo;
    QString msg = root["MSG"].asCString();
    userinfo.id = root["Sender"].asCString();
    userinfo.nickname = root["NickName"].asCString();
    userinfo.sex = root["Sex"].asCString();
    userinfo.age = root["Age"].asCString();
    userinfo.headurl = root["HeadUrl"].asCString();
    userinfo.persig = root["PerSig"].asCString();
    userinfo.praise = root["Praise"].asCString();
    userinfo.birthday = root["BirthDay"].asCString();
    userinfo.star = root["Star"].asCString();
    userinfo.address = root["Address"].asCString();
    userinfo.phone = root["Phone"].asCString();
    userinfo.rubric = root["Rubric"].asCString();
    userinfo.zodiac = root["Zodiac"].asCString();
    fw->addItem(userinfo,msg);
    //同步到文件
    root["Status"] = -1;
    QString path;
    QString str = QCoreApplication::applicationDirPath();
    path = QString("%1/%2/friendRequest.json").arg(str).arg(m_userID);
    FILE* fp = NULL;
    fp = fopen(path.toStdString().c_str(),"r");
    if(fp == NULL)
    {
        fp = fopen(path.toStdString().c_str(),"w");
        if(fp)
        {
            Json::Value temp;
            temp.append(root);
            std::string content = temp.toStyledString();
            fwrite(content.c_str(),strlen(content.c_str()),1,fp);
            fflush(fp);
            fclose(fp);
            return;
        }
    }
    else
    {
        fseek(fp, 0, SEEK_END);
        int len = ftell(fp);
        fseek(fp, 0, SEEK_SET);
        char* buff = new char[len + 1];
        fread(buff, len, 1, fp);
        buff[len] = 0;
        Json::Reader reader;
        Json::Value temp;
        if (reader.parse(buff, temp))
        {
            fclose(fp);
            fp = NULL;
            fp = fopen(path.toStdString().c_str(), "w");
            if (fp)
            {
                temp.append(root);
                std::string content = temp.toStyledString();
                int len = strlen(content.c_str());
                fwrite(content.c_str(), len, 1, fp);
                fflush(fp);
                fclose(fp);
            }
        }
        delete [] buff;
        buff = nullptr;
    }
    //    fw->show();
}

void ChatSocket::handleAddFriendS(Json::Value &root)
{
    QString recv = root["Recv"].asCString();
    if(recv != m_userID)
        FriendRequestList::getInstance()->updateRequestStatus(recv,4);//对方同意
    else
        FriendRequestList::getInstance()->updateRequestStatus(recv,0);
    QList<UserInfo> listU;
    //读取好友信息
    for(int i=0;i < root["Friends"].size();++i)
    {
        UserInfo u;
        u.id = root["Friends"][i]["ID"].asCString();
        u.nickname = root["Friends"][i]["NickName"].asCString();
        int fstatus = root["Friends"][i]["Status"].asInt();
        u.headurl = root["Friends"][i]["HeadUrl"].asCString();
        u.online = fstatus;
        listU.append(u);
    }
    //更新好友信息到自己的数据库
//    ChatDB::getInstance()->updateUserInfo(root["Friends"],1);
    //读取群聊信息
    QList<groupinfo> listG;
    for(int i = 0;i < root["Groups"].size(); ++i)
    {
        groupinfo g;
        std::string gname = root["Groups"][i]["GNickName"].asString();
        std::string gheadpath = root["Groups"][i]["GHeadPath"].asString();
        std::string gid = root["Groups"][i]["GID"].asString();
        strcpy(g.gid,gid.c_str());
        strcpy(g.gimg,gheadpath.c_str());
        strcpy(g.gname,gname.c_str());
        listG.append(g);
    }
    MainWidget::getInstance()->loadFriendAndLoadGroup(listU,listG);
}

void ChatSocket::handleAddFriendF(Json::Value &root)
{
    QString recv = root["Recv"].asCString();
    if(recv == m_userID)
        FriendRequestList::getInstance()->updateRequestStatus(recv,3);
    else
        FriendRequestList::getInstance()->updateRequestStatus(recv,1);
}

void ChatSocket::sendTextMsg(QString msg,QString recv)
{
    QString copymsg = msg;
    qDebug()<<msg<<endl;
    Json::Value root;
    root["TYPE"] = TEXT_MSG;
    QDateTime current_date_time = QDateTime::currentDateTime();
    QString current_date = current_date_time.toString("yyyy-MM-dd hh:mm:ss");
    root["time"] = current_date.toStdString().c_str();
    root["sender"] = m_userID.toStdString().c_str();
    QString recvobj = recv;//获取接收人账号
    int i = recvobj.indexOf('(');
    recvobj =recvobj.replace(")","");
    recvobj = recvobj.mid(i+1);
    root["receiver"] = recvobj.toStdString().c_str();
    root["msg"] = msg.toStdString().c_str();
    QString strJson(root.toStyledString().c_str());
    int len = strJson.toUtf8().length();
    m_pChatSock->write((char*)&len,sizeof (len));
    //发送消息
    m_pChatSock->write(strJson.toUtf8(),len);
    //还原
    msg = copymsg;
    //消息更新到好友列表
//    MainUI::getInstance().updateFriendList(u,-2,msg);
    //每次发完消息  保存到文件
    QString str = QCoreApplication::applicationDirPath();
    QString filename = QString("%1/%2/%3-%4.txt").arg(str).arg(m_userID).arg(m_userID).arg(recvobj);
    QFile file(filename);
    if(!file.open(QIODevice::ReadWrite|QIODevice::Append))
    {
        QMessageBox::warning(NULL,"警告","创建文件失败");
        return;
    }
    current_date= m_userID + "&" + current_date + "\r\n";
    file.write(current_date.toStdString().c_str());
    msg = "わ" + msg + "わ\r\n";
    file.write(msg.toStdString().c_str());
    file.close();
}

void ChatSocket::handleChatDate()
{
    int len = 0;
    m_pChatSock->read((char*)&len,sizeof(int));
    int recvsize = 0,currecvsize = 0;
    char* buff = new char[len+1];
    while(recvsize < len)
    {
        currecvsize = m_pChatSock->read(buff+recvsize,len-recvsize);
        recvsize += currecvsize;
    }
    buff[len] = 0;
    Json::Reader reader;
    Json::Value root;
    int type = -1;
    if(reader.parse(buff,root))
        type = root["TYPE"].asInt();
    switch ((TYPE)type)
    {
    case LOG_IN_F:
    {
        emit ChatSocket::transMSG(MsgType::LOGINF,"用户名或密码不正确或重复登陆!");
        break;
    }
    case LOG_IN_S:
    {
        handleLoginS(root);
        break;
    }
    case RES_F:
        QMessageBox::critical(NULL,"提示","注册失败");
        break;
    case RES_S:
    {
        QString uid(root["UID"].asCString());
        QString nickname(root["nickName"].asCString());
        QMessageBox::information(NULL,"提示",QString("注册成功您的账号是:" + uid));
        RegisterUI::getInstance()->close();
        Widget::getInstance()->fillUID(uid);
        ChatDB::getInstance()->addUser(uid,nickname);
        break;
    }
    case ONLINE:
    {
        hanldeOnlineStatus(root["object"].asCString(),true);
        break;
    }
    case OFFLINE:
    {
        hanldeOnlineStatus(root["object"].asCString(),false);
        break;
    }
    case SECURE_RESPOND_S:
    {
//        handlerSecure_Response_S();
        break;
    }
    case SECURE_RESPOND_F:
    {
        QMessageBox::warning(NULL,"警告","密保回答错误,请重新回答");
        break;
    }
    case RESET_PWD_S:
        QMessageBox::information(NULL,"提示","密码重置成功");
        break;
    case RESET_PWD_F:
        QMessageBox::warning(NULL,"提示","密码重置失败");
        break;
    case TEXT_MSG:
        handleRecvMsg(root);
        break;
    case REQUEST_OFFLINELOG:
        handleOffLineLog(root);
        break;
    case SEARCH_USER:
        emit transSearchResult(root);
        break;
    case ADD_FRIEND:
        handleAddFriend(root);
        break;
    case ADD_FRIEND_S:
        handleAddFriendS(root);
        break;
    case ADD_FRIEND_F:
        handleAddFriendF(root);
        break;
    default:
        break;
    }
    delete [] buff;
    buff = nullptr;
}

void ChatSocket::handleStatuChange(QAbstractSocket::SocketState socketState)
{
    switch (socketState) {
    case QAbstractSocket::ConnectedState://已连接
        m_ConnectionStatus = true;
        emit ChatSocket::transMSG(MsgType::CONNECTED);
        break;
    case QAbstractSocket::ClosingState://断开连接
        break;
    default:
        break;
    }
}

void ChatSocket::onLogin(QString id, QString pwd, bool isSavePwd)
{
    m_userID = id;
    m_pwd = pwd;
    m_isSavePwd = isSavePwd;
    Json::Value root;
    root["UID"] = id.toStdString();
    root["PWD"] = pwd.toStdString();
    root["TYPE"] = LOG_IN;
    qDebug() << id << pwd << "\n";
    QString str(root.toStyledString().c_str());
    int len = str.toUtf8().length();
    m_pChatSock->write((char*)&len,sizeof len);
    qDebug()<< m_pChatSock->write(str.toUtf8(),str.toUtf8().length()) << endl;
}
